#ifndef _MPxManipContainer
#define _MPxManipContainer
//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc., and/or its licensors.  All
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related
// material (collectively the "Data") in these files contain unpublished
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its
// licensors,  which is protected by U.S. and Canadian federal copyright law
// and by international treaties.
//
// The Data may not be disclosed or distributed to third parties or be
// copied or duplicated, in whole or in part, without the prior written
// consent of Autodesk.
//
// The copyright notices in the Software and this entire statement,
// including the above license grant, this restriction and the following
// disclaimer, must be included in all copies of the Software, in whole
// or in part, and all derivative works of the Software, unless such copies
// or derivative works are solely in the form of machine-executable object
// code generated by a source language processor.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,
// OR ARISING FROM A COURSE OF DEALING, USAGE, OR TRADE PRACTICE. IN NO
// EVENT WILL AUTODESK AND/OR ITS LICENSORS BE LIABLE FOR ANY LOST
// REVENUES, DATA, OR PROFITS, OR SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK AND/OR ITS LICENSORS HAS
// BEEN ADVISED OF THE POSSIBILITY OR PROBABILITY OF SUCH DAMAGES.
// ==========================================================================
//+
//
// CLASS:    MPxManipContainer
//
// ****************************************************************************

#if defined __cplusplus

// ****************************************************************************
// INCLUDED HEADER FILES


#include <maya/MStatus.h>
#include <maya/MTypes.h>
#include <maya/MObject.h>
#include <maya/MPxNode.h>
#include <maya/MPlug.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MTypeId.h>
#include <maya/MString.h>
#include <maya/M3dView.h>
#include <maya/MDagPath.h>
#include <maya/MObjectArray.h>
#include <maya/MManipData.h>
#include <maya/MPxManipulatorNode.h>

// ****************************************************************************
// DECLARATIONS


// ****************************************************************************
// CLASS DECLARATION (MPxManipContainer)

//! \ingroup OpenMayaUI MPx
//! \brief Base class for user defined manipulator containers 
/*!
MPxManipContainer is the base class for user-defined container
manipulators.  This class is derived from MPxNode since manipulators
in Maya are dependency nodes.

MPxManipContainer is a container manipulator that has at least one
base manipulator. MPxManipContainer has methods for adding the
following base manipulators types to the container:
FreePointTriadManip, DirectionManip, DistanceManip, PointOnCurveManip,
PointOnSurfaceManip, DiscManip, CircleSweepManip, ToggleManip,
StateManip, and CurveSegmentManip.

A container manipulator has one converter which is the interface
between the container's children manipulators and the node plugs they
affect.  The values on the converter that are related to children
manipulators are called converterManipValues, and the values on the
converter that are related to the node plugs are called
converterPlugValues.

The conversion between converterManipValues and converterPlugValues
are performed through conversion callback methods, except when there
is a one-to-one connection between a converterManipValue and a
converterPlugValue.

There are two kinds of conversion callback methods: manipToPlug and
plugToManip.  A plugToManipConversionCallback is used to calculate a
converterManipValue from various converterPlugValues.  This callback
has access to all the converterPlugValues and returns the value of a
converterManipValue.  A manipToPlugConversionCallback is used to
calculate a converterPlugValue from various converterManipValues. This
callback has access to all the converterManipValues and returns the
value of a converterPlugValue.

In order for an MPxManipContainer to be able to run, the manipulator
needs to know that the initialization is finished through the
finishAddingManips method.
*/
class OPENMAYAUI_EXPORT MPxManipContainer : public MPxNode
{
public:
	//! \brief Pointer to a plug-to-manip conversion callback function.
	/*!
	 \param[in] manipIndex Index of the manipulator value to be calculated.
	*/
	typedef MManipData (MPxManipContainer::*plugToManipConversionCallback)(unsigned int manipIndex);

	//! \brief Pointer to a manip-to-plug conversion callback function.
	/*!
	 \param[in] plugIndex Index of the plug value to be calculated.
	*/
	typedef MManipData (MPxManipContainer::*manipToPlugConversionCallback)(unsigned int plugIndex);

	//! Built-in manipulator types.
	enum baseType {
		kFreePointTriadManip,	//!< \nop
		kDirectionManip,	//!< \nop
		kDistanceManip,		//!< \nop
		kPointOnCurveManip,	//!< \nop
		kPointOnSurfaceManip,	//!< \nop
		kDiscManip,		//!< \nop
		kCircleSweepManip,	//!< \nop
		kToggleManip,		//!< \nop
		kStateManip,		//!< \nop
		kCurveSegmentManip,	//!< \nop
		kCustomManip		//!< \nop
	};

	MPxManipContainer();
	virtual ~MPxManipContainer();
	virtual MPxNode::Type type() const;
	static  MStatus		initialize();
	static MPxManipContainer * newManipulator(const MString &manipName,
											  MObject &manipObject,
											  MStatus *ReturnStatus = NULL);

	// Methods to overload
	virtual void			draw(M3dView &view,
								 const MDagPath &path,
								 M3dView::DisplayStyle style,
								 M3dView::DisplayStatus status);
	virtual MStatus			connectToDependNode(const MObject &dependNode);

	// Do not put any of these functions in the constructor.
	virtual MStatus			createChildren();

	MDagPath	addFreePointTriadManip		(const MString &manipName,
											 const MString &pointName);
	MDagPath	addDirectionManip			(const MString &manipName,
											 const MString &directionName);
	MDagPath	addDistanceManip			(const MString &manipName,
											 const MString &distanceName);
	MDagPath	addPointOnCurveManip		(const MString &manipName,
											 const MString &paramName);
	MDagPath	addPointOnSurfaceManip		(const MString &manipName,
											 const MString &paramName);
	MDagPath	addDiscManip				(const MString &manipName,
											 const MString &angleName);
	MDagPath	addCircleSweepManip			(const MString &manipName,
											 const MString &angleName);
	MDagPath	addToggleManip				(const MString &manipName,
											 const MString &toggleName);
	MDagPath	addStateManip				(const MString &manipName,
											 const MString &stateName);
	MDagPath	addCurveSegmentManip		(const MString &manipName,
											 const MString &startParamName,
											 const MString &endParamName);
	MDagPath	addRotateManip				(const MString &manipName,
											 const MString &rotationName);
	MDagPath	addScaleManip				(const MString &manipName,
											 const MString &scaleName);
	MStatus	addMPxManipulatorNode		(const MString &manipTypeName,
											 const MString &manipName,
											 MPxManipulatorNode*& proxyManip );
	bool					isManipActive(const MFn::Type& manipType,
											MObject &manipObject);
	MStatus                 finishAddingManips();
    static MStatus          addToManipConnectTable(MTypeId &);
    static MStatus          removeFromManipConnectTable(MTypeId &);

	virtual MManipData plugToManipConversion( unsigned int manipIndex );
	virtual MManipData manipToPlugConversion( unsigned int manipIndex );

	void addPlugToManipConversion( unsigned int manipIndex );
	unsigned int addManipToPlugConversion( MPlug &plug );

BEGIN_NO_SCRIPT_SUPPORT:

	//!	NO SCRIPT SUPPORT
	void addPlugToManipConversionCallback(
			unsigned int manipIndex,
			plugToManipConversionCallback callback
		);

	//!	NO SCRIPT SUPPORT
	unsigned int addManipToPlugConversionCallback(
			MPlug &plug,
			manipToPlugConversionCallback callback
		);

END_NO_SCRIPT_SUPPORT:

	MStatus	getConverterManipValue(unsigned int manipIndex, unsigned int &value);
	MStatus	getConverterManipValue(unsigned int manipIndex, double &value);
	MStatus	getConverterManipValue(unsigned int manipIndex, double &x, double &y);
	MStatus	getConverterManipValue(unsigned int manipIndex, MPoint &point);
	MStatus	getConverterManipValue(unsigned int manipIndex, MVector &vector);
	MStatus	getConverterManipValue(unsigned int manipIndex, MMatrix &matrix);
	MStatus	getConverterManipValue(unsigned int manipIndex,
								   MEulerRotation &rotation);
	MStatus	getConverterManipValue(unsigned int manipIndex,
								   MTransformationMatrix &xform);

	MStatus	getConverterPlugValue(unsigned int plugIndex, double &value);
	MStatus	getConverterPlugValue(unsigned int plugIndex, double &x, double &y);
	MStatus	getConverterPlugValue(unsigned int plugIndex, MPoint &point);
	MStatus	getConverterPlugValue(unsigned int plugIndex, MVector &vector);
	MStatus	getConverterPlugValue(unsigned int plugIndex, MMatrix &matrix);
	MStatus	getConverterPlugValue(unsigned int plugIndex,
								  MEulerRotation &rotation);

	virtual MStatus	doPress();
	virtual MStatus	doDrag();
	virtual MStatus	doRelease();

    static const char *     className();

protected:
// No protected members

private:
	friend class			MFnPlugin;
	void *					internalData;
};

//	These typedefs provide backward compatability for plugins which were
//	written back when the callback types were declared outside of the
//	the class's namespace.
typedef MPxManipContainer::manipToPlugConversionCallback manipToPlugConversionCallback;
typedef MPxManipContainer::plugToManipConversionCallback plugToManipConversionCallback;

#endif /* __cplusplus */
#endif /* _MPxManipContainer */
